Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement optional pretty printed stacktraces #2420

Merged
merged 8 commits into from
Feb 21, 2019

Conversation

codablock
Copy link

@codablock codablock commented Nov 5, 2018

This solves something that is very much on top of my "Why I hate C++" list. I lost so much time already hunting exceptions/segfaults which only happened sporadically in tests. With this PR, you can add --enable-stacktraces to ./configure, which will give you pretty stacktraces on nearly all kinds of crashes that might happen. It also adds better default handling for catched unknown (catch(...)) exceptions.

This works on Linux and Windows (only MinGW based, native and wine). On Linux it uses backtrace() from execinfo.h to gather the stack trace and StackWalk64 on Windows. It then uses libbacktrace to extract symbol information. It is required to have debug information enabled, so configure.ac will add -g to the compiler flags, but still build with optimization (if --enable-debug is not given at the same time).

For all this to work, I had to "hack" into the C++ ABI by using -Wl,-wrap. It wraps a few of the ABI methods and gathers the stacktrace before actually doing the exception handling. GetExceptionStacktraceStr is then able to retrieve the stacktrace from a catched exception.

This method only works on GCC. For Clang based builds, I implemented dlsym(RTLD_NEXT, ...) based hooks into the C++ standard libs. This is untested currently as I don't have a Mac to test this. Would be happy if someone could test this and give feedback (@UdjinM6 @nmarley maybe). At least it's able to compile...so I have some hope it works :)

MacOS support is not complete yet, as it requires some changes to the build system. We specifically need to generate .dSYM bundles which contain the necessary debug symbols. Until then, --enable-stacktraces will produce many libbacktrace errors in the debug output and not show any useful information about stacktraces.

@codablock
Copy link
Author

FYI, if this turns out to work well enough, we could also consider adding tracing of stacktraces to the deadlock detector. Depends on how slow the stacktrace gathering is in the end...

@codablock
Copy link
Author

Another option is to always build with stacktrace support enabled and make it a runtime option. It would then be disabled by default in a way that it does not create any overhead (bail out immediately from wrapped ABIs)

@UdjinM6
Copy link

UdjinM6 commented Nov 6, 2018

macos 10.14.1 (18B75)

> ./src/test/test_dash 
Running 250 test cases...
libbacktrace error: 0 - libbacktrace could not find executable to open
libbacktrace error: -1 - failed to read executable information
libbacktrace error: -1 - failed to read executable information
libbacktrace error: -1 - failed to read executable information
libbacktrace error: -1 - failed to read executable information
#### std::terminate() called, aborting ####
#### UNCAUGHT EXCEPTION ####
Exception: type=, what="whoops"
   0#: (0x00000000) <unknown-file> - ???
   1#: (0x00000000) <unknown-file> - ???
   2#: (0x00000000) <unknown-file> - ???
   3#: (0x00000000) <unknown-file> - ???
   4#: (0x00000000) <unknown-file> - ???
unknown location:0: fatal error: in "evo_dip3_activation_tests/dip3_activation": signal: SIGABRT (application abort requested)
test/test_dash.cpp:83: last checkpoint
Segmentation fault: 11

@codablock
Copy link
Author

@UdjinM6 Can you try it again if you find time?

@UdjinM6
Copy link

UdjinM6 commented Nov 9, 2018

> ./src/dashd --regtest
4559648916, , 0, 
140734756526909, , 0, 
0, , 0, 
4559656182, , 0, 
140734756561721, , 0, 
140734756573863, , 0, 
140734756557893, , 0, 
sis=7
lstr=<unknown-file>
lstr=<unknown-file>
lstr=<unknown-file>
lstr=<unknown-file>
lstr=<unknown-file>
lstr=<unknown-file>
lstr=<unknown-file>
s2= 0#: (0x10FC6B894) <unknown-file> - ???

s2= 1#: (0x7FFF5D2B9B3D) <unknown-file> - ???

s2= 2#: (0x00000000) <unknown-file> - ???

s2= 3#: (0x10FC6D4F6) <unknown-file> - ???

s2= 4#: (0x7FFF5D2C2339) <unknown-file> - ???

s2= 5#: (0x7FFF5D2C52A7) <unknown-file> - ???

s2= 6#: (0x7FFF5D2C1445) <unknown-file> - ???

#### signal Segmentation fault: 11 ####
   0#: (0x10FC6B894) <unknown-file> - ???
   1#: (0x7FFF5D2B9B3D) <unknown-file> - ???
   2#: (0x00000000) <unknown-file> - ???
   3#: (0x10FC6D4F6) <unknown-file> - ???
   4#: (0x7FFF5D2C2339) <unknown-file> - ???
   5#: (0x7FFF5D2C52A7) <unknown-file> - ???
   6#: (0x7FFF5D2C1445) <unknown-file> - ???
Abort trap: 6

@codablock
Copy link
Author

Turned out Mac support was never merged into libbacktrace (ianlancetaylor/libbacktrace#2). But the necessary code is used by the Rust devs in https://github.com/rust-lang-nursery/libbacktrace/tree/rust-snapshot-2018-05-22 (they were also the ones who created the initial PR). I changed backtrace.mk to use this repo instead of the upstream repo until Mac support is officially supported by the upstream version. @UdjinM6 If you find time...one last try...if it still doesn't work I give up for now.

@UdjinM6
Copy link

UdjinM6 commented Nov 10, 2018

> ./src/dashd --regtest
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
exeFileName: /Developer/Projects/crypto/dash_develop/./src/dashd
libbacktrace error: -1 - no debug info in Mach-O executable
#### signal Segmentation fault: 11 ####

Abort trap: 6

@codablock
Copy link
Author

So, after some investigation it looks like stacktraces on Mac will require more work in the build system. We need to manually generate .dSYM bundles with debug information to make make libbacktrace work on Mac OS. I'll leave it as it is now, simply don't use --enable-stacktraces on Mac for now.

A build is running atm that does a test crash. I'll post a link to it later.

@codablock codablock changed the title Implement optional pretty printed stacktraces [WIP] Implement optional pretty printed stacktraces Nov 27, 2018
@codablock codablock force-pushed the pr_stacktraces branch 2 times, most recently from c1bbc1d to c3008c5 Compare January 28, 2019 13:27
This is currently only useful to extract symbols. It fails to gather
stacktraces when compiled with MinGW, so we can only use it to get symbol
information from a stack trace which we gathered outside of libbacktrace.
This is a hack and should only be used for debugging. It works by wrapping
the C++ ABI __wrap___cxa_allocate_exception. The wrapper records a backtrace
and stores it in a global map. Later the stacktrace can be retrieved with
GetExceptionStacktraceStr.

This commit also adds handlers to pretty print uncaught exceptions and
signals.
@codablock
Copy link
Author

codablock commented Feb 19, 2019

Rebased this branch and reworked a few things. The last Travis build contains a few test crashes so that you can see how stacktraces look like.

Unfortunately, the stack traces get all mixed up when walking too deep, but this is something I currently have no good solution for. Reason is that the backtrace() call done in GetStackFrames returns too many stack frames, so that it goes beyond the entry point of the process/thread.

I've disabled stacktraces on the win32/win64 Travis builds for now, as the added debug info results in binaries with multiple hundred MBs of size, causing the linker to take ages (which times out on Travis). If future mingw versions turn out to perform better, we might enable stacktraces for win32/win64 on Travis.

MacOS is not supported for now. I've also updated the PR description to make this clear.

I'm going to remove the WIP status now, meaning that I'm happy to see reviews and eventually ACKs :)
I'll remove the test crashes when ACKs come in.

@codablock codablock changed the title [WIP] Implement optional pretty printed stacktraces Implement optional pretty printed stacktraces Feb 19, 2019
@UdjinM6 UdjinM6 added this to the 14.0 milestone Feb 19, 2019
@UdjinM6
Copy link

UdjinM6 commented Feb 19, 2019

Looks good 👍

Otherwise the code at the bottom is never executed when nodes crash,
leading to no output of debug.log files on Travis.
@codablock
Copy link
Author

Removed the test crashes and force-pushed

@UdjinM6
Copy link

UdjinM6 commented Feb 21, 2019

Shouldn't we also drop TestCrash, DoCrash etc.?

@codablock
Copy link
Author

@UdjinM6 Yepp, should have removed them, which I did now.

Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

utACK

@UdjinM6 UdjinM6 merged commit 48d92f1 into dashpay:develop Feb 21, 2019
nmarley added a commit to nmarley/dash that referenced this pull request Sep 16, 2019
nmarley added a commit to nmarley/dash that referenced this pull request Sep 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants